﻿/// <reference path="libs/knockout-2.2.1.js" />
/// <reference path="libs/mongoLab.js" />
/// <reference path="libs/knockout.validation.js" />
/// <reference path="libs/sammy.js" />

var CashRegister = Class.create({
    initialize: function (balance) {
        this.balance = balance;
    },

    getCashInUSD: function () {
        return this.balance * 1.5;
    },

    getCashInEuro: function () {
        return this.balance * 1.98;
    },

    add: function (amount) {
        this.balance += amount;
    },

    remove: function (amount) {
        this.balance -= amount;
    }
});

// Product VM
var ProductVM = Class.create({
    initialize: function (productName, price) {
        this.productName = ko.observable(productName).extend({
            validatable: true,
            required: true,
            pattern: {
                message: 'Name is not valid!',
                params: '^[a-zA-Z].*'
            }
        });
        this.price = ko.observable(price).extend({
            validatable: true,
            required: true,
            pattern: {
                message: 'Price is not valid',
                params: '^[0-9].*'
            }
        });
    },
});

// Storage module - coresponding with MongoDB
var Storage = (function () {

    var myDB = new MongoLab('9BJSnaAJTSwCpdM351kcswJP_ZjTA8LW');

    //this.initialize = function (setOfProducts) {
    //    this.count = 0;
    //    if (setOfProducts) {
    //        for (var i = 0; i < setOfProducts.length; i++) {
    //            myDB.insertDocuments('simple_catalog_telerik', 'products', setOfProducts[i]);
    //            this.count++;
    //        }
    //    }

    //    that = this;
    //};

    // Adds a array of products to the DB
    this.addProducts = function (product) {
        myDB.insertDocuments('simple_catalog_telerik', 'products', product, function () {
        });
        this.count++;
    };

    // Search for products by a JSON paramether
    this.searchForProducts = function (params, getResult) {
        myDB.listDocuments('simple_catalog_telerik', 'products', params, function (products) {
            getResult(products);
        });
    };

    // Gets all the products form MongoDB
    this.getAllProducts = function (getResult) {
        myDB.listDocuments('simple_catalog_telerik', 'products', function (products) {
            getResult(products);
        });
    };

    // TODO - implemnt
    this.deleteProduct = function (product) {
        //localStorage.removeItem(product.productName);
        this.count--;
    };

    return {
        addProducts: addProducts,
        getAllProducts: getAllProducts,
        searchForProducts: searchForProducts
    };
})();

var SiteComponents = (function () {

    // Add form VM
    var AddForm = Class.create({
        initialize: function (products) {

            var self = this;
            self.products = ko.observableArray();


            self.addProduct = function () {
                self.products.push(new ProductVM("", ""));
            };

            // removes a row from the adding form
            self.removeProduct = function (product) {
                self.products.remove(product);
            };

            // On Send to DB button click
            self.save = function () {

                self.errors = ko.validation.group(self.products(), { deep: true });
                console.log(self.errors());

                if (self.errors().length != 0) {
                    self.errors.showAllMessages();
                }
                else {
                    self.lastSavedJson(JSON.stringify(ko.toJS(self.products), null, 2));
                    Storage.addProducts(ko.toJS(self.products));

                    $("#done-send").html('Sended to DB!');
                }
            };

            self.lastSavedJson = ko.observable("");

            // adds the first row in advance
            self.addProduct();
        },
        render: function () {
            ko.applyBindings(new AddForm(), $('#add-form')[0]);
        }
    });

    // Search form VM
    var SearchForm = Class.create({
        initialize: function (products) {

            var self = this;
            self.products = ko.observableArray(ko.utils.arrayMap(products, function (product) {
                return {
                    productName: product.productName,
                    price: product.price
                };
            }));

            self.addProduct = function () {
                self.products.push(new ProductVM("", ""));
            };

            var searchGrid = new GridPageViewModel();
            ko.applyBindings(searchGrid, $('#result-grid')[0]);

            self.search = function () {

                var searchQuery = {};

                if (!ko.toJS(self.products)[0].price) {
                    searchQuery = {
                        productName: ko.toJS(self.products)[0].productName
                    }
                }
                else {
                    searchQuery = ko.toJS(self.products)[0];
                }

                console.log(searchQuery);

                Storage.searchForProducts(searchQuery, function (data) {

                    self.products.pop();

                    console.log(searchGrid)

                    $(document).ready(function () {
                        for (var i = 0; i < data.length; i++) {
                            var item = data[i];
                            searchGrid.addProduct(item.productName, item.price);
                        }
                    });
                })
            };

            // adds the first row in advance
            self.addProduct();

            self.lastSavedJson = ko.observable("");

        },

        render: function () {
            ko.applyBindings(new SearchForm(), $('#search-form')[0]);
        }
    });

    // Grid VM
    var GridPageViewModel = Class.create({

        initialize: function () {

            var self = this;
            self.sortedPriceDesc = ko.observable(false);
            self.sortedNameDesc = ko.observable(false);
            self.sortedPriceAsc = ko.observable(false);
            self.sortedNameAsc = ko.observable(false);

            self.products = ko.observableArray([]);

            self.addProduct = function (productName, price) {
                var newPoduct = new ProductVM(productName, price);
                self.products.push(newPoduct);
            };

            self.sortByName = function () {
                self.sortedPriceDesc(false);
                self.sortedNameDesc(true);
                self.sortedNameAsc(false);
                self.sortedPriceAsc(false);

                self.products.sort(function (a, b) {
                    return a.productName() < b.productName() ? -1 : 1;
                });
            };

            self.sortByPrice = function () {
                self.sortedPriceDesc(true);
                self.sortedNameDesc(false);
                self.sortedNameAsc(false);
                self.sortedPriceAsc(false);

                self.products.sort(function (a, b) {
                    return parseFloat(a.price()) < parseFloat(b.price()) ? -1 : 1;
                });
            };

            self.sortByNameAsc = function () {
                self.sortedPriceDesc(false);
                self.sortedNameDesc(false);
                self.sortedNameAsc(true);
                self.sortedPriceAsc(false);

                self.products.sort(function (a, b) {
                    return a.productName() > b.productName() ? -1 : 1;
                });
            };

            self.sortByPriceAsc = function myfunction() {
                self.sortedPriceDesc(false);
                self.sortedNameDesc(false);
                self.sortedNameAsc(false);
                self.sortedPriceAsc(true);

                self.products.sort(function (a, b) {
                    return parseFloat(a.price()) > parseFloat(b.price()) ? -1 : 1;
                });
            }

            self.jumpToFirstPage = function () {
                self.gridViewModel.currentPageIndex(0);
            };

            self.gridViewModel = new ko.simpleGrid.viewModel({
                data: self.products,
                columns: [
                    { headerText: "Product Name", rowText: "productName" },
                    { headerText: "Price", rowText: "price" },
                ],
                pageSize: 10
            });
        }
    });

    // Top Menu VM
    var TopMenu = Class.create({

        initialize: function () {
            // Data
            var self = this;
            self.menus = ['List Catalog', 'Add Product', 'Search for product'];
            self.chosenMenuId = ko.observable();
            self.chosenMenuData = ko.observable();

            // Behavor
            self.goToMenu = function (menu) {

                var ulrHashes = [];
                ulrHashes['List Catalog'] = 'list';
                ulrHashes['Add Product'] = 'add';
                ulrHashes['Search for product'] = 'search';

                location.hash = ulrHashes[menu];
            };

            Sammy(function () {
                this.get('#list', function () {
                    self.chosenMenuId(this.params.menu);
                    $('#site-main').load('../content/catalog-list.html', function () {
                        render();
                    });
                })

                this.get('#add', function () {
                    self.chosenMenuId(this.params.menu);
                    $('#site-main').load('../content/add-form.html', function () {
                        var myAddForm = new AddForm();
                        myAddForm.render();
                    });
                })
                this.get('#search', function () {
                    self.chosenMenuId(this.params.menu);
                    $('#site-main').load('../content/search-form.html', function () {
                        var mySearchForm = new SearchForm();
                        mySearchForm.render();
                    });
                })

                this.get('', function () { this.app.runRoute('get', '#list') });
            }).run();
        },

        render: function () {
            ko.applyBindings(new TopMenu(), $('#header')[0]);
        }

    });

    return {
        getTopMenu: function () {
            return new TopMenu();
        },
        
        getGridViewVM: function () {
            return new GridPageViewModel();
        },

        getAddForm: function () {
            return new AddForm();
        },

        getSearchForm: function () {
            return new SearchForm();
        }
    }
})();

var Catalog = (function () {
    var i = 0;
    var j = 0;

    // Store Logic
    this.initCatalog = function initStore() {
        _createCashRegister();

        var myTopMenu = SiteComponents.getTopMenu();
        myTopMenu.render();

        //($('section').on('click', function() {
        //    $('section').removeClass('active');
        //    this.addClass('active');
        //}))();
    }

    // renders GridView content
    this.render = function () {

        // Generating all the content form the DB to HTML
        Storage.getAllProducts(function (data) {

            var listGrid = SiteComponents.getGridViewVM();

            $(document).ready(function () {
                for (var i = 0; i < data.length; i++) {
                    var item = data[i];
                    listGrid.addProduct(item.productName, item.price);
                }

                ko.applyBindings(listGrid, $('#grid-view')[0]);
            });

        });
    };

    // cash register generation and visualisation
    this._createCashRegister = function () {
        this.reg = new CashRegister();
        var cashRegister = $('<div id="cash-register"> \
            <p>Balance in leva: ' + reg.balance + ' lv. </p> \
            <p>Balance in USD: ' + reg.getCashInUSD() + ' eruo </p> \
            <p>Balance in Euro: ' + reg.getCashInEuro() + ' $ </p> \
            </div>');
        $('#cash').append(cashRegister);
    }

    // needed methods returns
    return {
        initCatalog: initCatalog,
    }
})();